<!DOCTYPE html>
<html class="client-nojs vector-feature-night-mode-disabled vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-sticky-header-enabled" lang="en" dir="ltr"><head>
<meta charset="UTF-8">
<title>Java Native Interface</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="canonical" href="https://en.wikipedia.org/wiki/Java_Native_Interface"> <link href="./mw/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/skins.vector.styles.css" rel="stylesheet" type="text/css">
<link href="./mw/user.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link rel="stylesheet" type="text/css" href="./mw/site.styles.css">
<link rel="stylesheet" type="text/css" href="./mw/noscript.css">
<link rel="stylesheet" type="text/css" href="./footer.css">
<link rel="stylesheet" type="text/css" href="./vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-Java_Native_Interface rootpage-Java_Native_Interface skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading">
<span id="openzim-page-title" class="mw-page-title-main"><span class="mw-page-title-main">Java Native Interface</span></span>
</h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="en" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr">
<style data-mw-deduplicate="TemplateStyles:r1236090951">
/* start https://en.wikipedia.org/ */
.mw-parser-output .hatnote{font-style:italic}.mw-parser-output div.hatnote{padding-left:1.6em;margin-bottom:0.5em}.mw-parser-output .hatnote i{font-style:normal}.mw-parser-output .hatnote+link+.hatnote{margin-top:-0.5em}@media print{body.ns-0 .mw-parser-output .hatnote{display:none!important}}
/* end https://en.wikipedia.org/ */
</style><div role="note" class="hatnote navigation-not-searchable">"JNI" redirects here. For other uses, see <a href="JNI_(disambiguation)" class="mw-disambig" title="JNI (disambiguation)">JNI (disambiguation)</a>.</div>
<style data-mw-deduplicate="TemplateStyles:r1305433154">
/* start https://en.wikipedia.org/ */
.mw-parser-output .ambox{border:1px solid #a2a9b1;border-left:10px solid #36c;background-color:#fbfbfb;box-sizing:border-box}.mw-parser-output .ambox+link+.ambox,.mw-parser-output .ambox+link+style+.ambox,.mw-parser-output .ambox+link+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+style+.ambox,.mw-parser-output .ambox+.mw-empty-elt+link+link+.ambox{margin-top:-1px}html body.mediawiki .mw-parser-output .ambox.mbox-small-left{margin:4px 1em 4px 0;overflow:hidden;width:238px;border-collapse:collapse;font-size:88%;line-height:1.25em}.mw-parser-output .ambox-speedy{border-left:10px solid #b32424;background-color:#fee7e6}.mw-parser-output .ambox-delete{border-left:10px solid #b32424}.mw-parser-output .ambox-content{border-left:10px solid #f28500}.mw-parser-output .ambox-style{border-left:10px solid #fc3}.mw-parser-output .ambox-move{border-left:10px solid #9932cc}.mw-parser-output .ambox-protection{border-left:10px solid #a2a9b1}.mw-parser-output .ambox .mbox-text{border:none;padding:0.25em 0.5em;width:100%}.mw-parser-output .ambox .mbox-image{border:none;padding:2px 0 2px 0.5em;text-align:center}.mw-parser-output .ambox .mbox-imageright{border:none;padding:2px 0.5em 2px 0;text-align:center}.mw-parser-output .ambox .mbox-empty-cell{border:none;padding:0;width:1px}.mw-parser-output .ambox .mbox-image-div{width:52px}@media(min-width:720px){.mw-parser-output .ambox{margin:0 10%}}@media print{body.ns-0 .mw-parser-output .ambox{display:none!important}}
/* end https://en.wikipedia.org/ */
</style><style data-mw-deduplicate="TemplateStyles:r1248332772">
/* start https://en.wikipedia.org/ */
.mw-parser-output .multiple-issues-text{width:95%;margin:0.2em 0}.mw-parser-output .multiple-issues-text>.mw-collapsible-content{margin-top:0.3em}.mw-parser-output .compact-ambox .ambox{border:none;border-collapse:collapse;background-color:transparent;margin:0 0 0 1.6em!important;padding:0!important;width:auto;display:block}body.mediawiki .mw-parser-output .compact-ambox .ambox.mbox-small-left{font-size:100%;width:auto;margin:0}.mw-parser-output .compact-ambox .ambox .mbox-text{padding:0!important;margin:0!important}.mw-parser-output .compact-ambox .ambox .mbox-text-span{display:list-item;line-height:1.5em;list-style-type:disc}body.skin-minerva .mw-parser-output .multiple-issues-text>.mw-collapsible-toggle,.mw-parser-output .compact-ambox .ambox .mbox-image,.mw-parser-output .compact-ambox .ambox .mbox-imageright,.mw-parser-output .compact-ambox .ambox .mbox-empty-cell,.mw-parser-output .compact-ambox .hide-when-compact{display:none}
/* end https://en.wikipedia.org/ */
</style>
<p>The <b>Java Native Interface</b> (<b>JNI</b>) is a <a href="Foreign_function_interface" title="Foreign function interface">foreign function interface</a> programming <a href="Software_framework" title="Software framework">framework</a> that enables <a href="Java_(programming_language)" title="Java (programming language)">Java</a> code running in a <a href="Java_virtual_machine" title="Java virtual machine">Java virtual machine</a> (JVM) to call and be called by<sup id="cite_ref-role_1-0" class="reference"><a href="#cite_note-role-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup> native applications (programs specific to a hardware and <a href="Operating_system" title="Operating system">operating system</a> platform) and <a href="Library_(computing)" title="Library (computing)">libraries</a> written in other languages such as <a href="C_(programming_language)" title="C (programming language)">C</a>, <a href="C%2B%2B" title="C++">C++</a> and <a href="Assembly_language" title="Assembly language">assembly</a>.
</p><p>Java 22 introduces the Foreign Function and Memory API, which can be seen as the successor to Java Native Interface.
</p>
<meta property="mw:PageProp/toc">
<div class="mw-heading mw-heading2"><h2 id="Objectives">Objectives</h2></div>
<p>JNI enables programmers to write native methods to handle situations when an application cannot be written entirely in the Java programming language, e.g. when the standard Java <a href="Class_(computer_science)" class="mw-redirect" title="Class (computer science)">class</a> <a href="Library_(computer_science)" class="mw-redirect" title="Library (computer science)">library</a> does not support the platform-specific features or program library. It is also used to modify an existing application (written in another programming language) to be accessible to Java applications. Many of the standard library classes depend on JNI to provide functionality to the developer and the user, e.g. file I/O and sound capabilities. Including performance- and platform-sensitive API implementations in the standard library allows all Java applications to access this functionality in a safe and platform-independent manner.
</p><p>The JNI framework lets a native method use Java <a href="Object_(computer_science)" title="Object (computer science)">objects</a> in the same way that Java code uses these objects. A native method can create Java objects and then inspect and use these objects to perform its tasks. A native method can also inspect and use objects created by Java application code.
</p><p>Only applications and signed applets can invoke JNI.
</p><p>An application that relies on JNI loses the platform portability Java offers (a partial workaround is to write a separate implementation of JNI code for each platform and have Java detect the operating system and load the correct one at runtime).
</p><p>Not only can native code interface with Java, it can also draw on a Java <code><a rel="nofollow" class="external text" href="https://docs.oracle.com/en/java/javase/24/docs/api/java.desktop/java/awt/Canvas.html">Canvas</a></code>, which is possible with the <a href="Java_AWT_Native_Interface" title="Java AWT Native Interface">Java AWT Native Interface</a>. The process is almost the same, with just a few changes. The Java AWT Native Interface is only available since <a href="Java_Platform%2C_Standard_Edition" title="Java Platform, Standard Edition">J2SE</a> 1.3.
</p><p>JNI also allows direct access to <a href="Assembly_language" title="Assembly language">assembly code</a>, without even going through a <a href="C_(programming_language)" title="C (programming language)">C</a> bridge.<sup id="cite_ref-2" class="reference"><a href="#cite_note-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup> Accessing Java applications from assembly is possible in the same way.<sup id="cite_ref-3" class="reference"><a href="#cite_note-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="Design">Design</h2></div>
<p>In the JNI framework, native functions are implemented in separate .c or .cpp files. (C++ provides a slightly simpler interface with JNI.) When the JVM invokes the function, it passes a <code>JNIEnv</code> pointer, a <code>jobject</code> pointer, and any Java arguments declared by the Java method. For example, the following converts a Java string to a native string:
</p>
<div class="mw-highlight mw-highlight-lang-cpp mw-content-ltr" dir="ltr"><pre><span class="k">extern</span><span class="w"> </span><span class="s">"C"</span>
<span class="n">JNIEXPORT</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">JNICALL</span><span class="w"> </span><span class="n">Java_ClassName_MethodName</span>
<span class="w"> </span><span class="p">(</span><span class="n">JNIEnv</span><span class="w"> </span><span class="o">*</span><span class="n">env</span><span class="p">,</span><span class="w"> </span><span class="n">jobject</span><span class="w"> </span><span class="n">obj</span><span class="p">,</span><span class="w"> </span><span class="n">jstring</span><span class="w"> </span><span class="n">javaString</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">nativeString</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">env</span><span class="o">-></span><span class="n">GetStringUTFChars</span><span class="p">(</span><span class="n">javaString</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="c1">//Do something with the nativeString</span>
<span class="w"> </span><span class="n">env</span><span class="o">-></span><span class="n">ReleaseStringUTFChars</span><span class="p">(</span><span class="n">javaString</span><span class="p">,</span><span class="w"> </span><span class="n">nativeString</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>The <i><code>env</code></i> pointer is a structure that contains the interface to the JVM. It includes all of the functions necessary to interact with the JVM and to work with Java objects. Example JNI functions are converting native arrays to/from Java arrays, converting native strings to/from Java strings, instantiating objects, throwing exceptions, etc. Basically, anything that Java code can do can be done using <code>JNIEnv</code>, albeit with considerably less ease.
</p><p>The argument <i><code>obj</code></i> is a reference to the Java object inside which this native method has been declared.
</p><p>Native <a href="Data_type" title="Data type">data types</a> can be mapped to/from Java data types. For compound types such as objects, <a href="Array_data_structure" class="mw-redirect" title="Array data structure">arrays</a> and <a href="String_(computer_science)" title="String (computer science)">strings</a> the native code must explicitly convert the data by calling methods in the <code>JNIEnv</code>.
</p><p>A JNI environment pointer (<style data-mw-deduplicate="TemplateStyles:r886049734">
/* start https://en.wikipedia.org/ */
.mw-parser-output .monospaced{font-family:monospace,monospace}
/* end https://en.wikipedia.org/ */
</style><span class="monospaced">JNIEnv*</span>) is passed as an argument for each native function mapped to a Java method, allowing for interaction with the JNI environment within the native method. This JNI interface pointer can be stored, but remains valid only in the current thread. Other threads must first call <span class="monospaced">AttachCurrentThread()</span> to attach themselves to the VM and obtain a JNI interface pointer. Once attached, a native thread works like a regular Java thread running within a native method. The native thread remains attached to the VM until it calls <span class="monospaced">DetachCurrentThread()</span> to detach itself.<sup id="cite_ref-4" class="reference"><a href="#cite_note-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup>
</p><p>The JNI framework does not provide any automatic garbage collection for non-JVM memory resources allocated by code executing on the native side. Consequently, native side code (such as assembly language) assumes the responsibility for explicitly releasing any such memory resources that the native code acquires.
</p><p>On Linux and Solaris platforms, if the native code registers itself as a signal handler, it could intercept signals intended for the JVM. A <a href="Chain-of-responsibility_pattern" title="Chain-of-responsibility pattern">chain of responsibility</a> can be used to allow native code to better inter-operate with the JVM. On Windows platforms, <a href="Microsoft-specific_exception_handling_mechanisms#Structured_Exception_Handling" title="Microsoft-specific exception handling mechanisms">Structured Exception Handling (SEH)</a> may be employed to wrap native code in SEH try/catch blocks so as to capture machine (CPU/FPU) generated software interrupts (such as NULL pointer access violations and divide-by-zero operations), and to handle these situations before the interrupt is propagated back up into the JVM (i.e. Java side code), in all likelihood resulting in an unhandled exception.
</p><p>The encoding used for the NewStringUTF, GetStringUTFLength, GetStringUTFChars, ReleaseStringUTFChars and GetStringUTFRegion functions is "modified UTF-8",<sup id="cite_ref-jniModifiedUtf_5-0" class="reference"><a href="#cite_note-jniModifiedUtf-5"><span class="cite-bracket">[</span>5<span class="cite-bracket">]</span></a></sup> which is not valid UTF-8 for all inputs, but a different encoding really. The null character (U+0000) and codepoints not on the <a href="Plane_(Unicode)#Basic_Multilingual_Plane" title="Plane (Unicode)">Basic Multilingual Plane</a> (greater than or equal to U+10000, i.e. those represented as <i>surrogate pairs</i> in UTF-16) are encoded differently in modified UTF-8. Many programs actually use these functions incorrectly and treat the UTF-8 strings returned or passed into the functions as standard UTF-8 strings instead of modified UTF-8 strings. Programs should use the NewString, GetStringLength, GetStringChars, ReleaseStringChars, GetStringRegion, GetStringCritical and ReleaseStringCritical functions, which use UTF-16LE encoding on little-endian architectures and UTF-16BE on big-endian architectures, and then use a UTF-16 to UTF-8 conversion routine.
</p><p>The typical use of JNI looks like the following, requiring the inclusion of a header <code><jni.h></code>:
</p>
<div class="mw-highlight mw-highlight-lang-c mw-content-ltr" dir="ltr"><pre><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><jni.h></span>
<span class="n">JNIEXPORT</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">JNICALL</span><span class="w"> </span><span class="n">Java_HelloJNI_sayHello</span><span class="p">(</span><span class="n">JNIEnv</span><span class="w"> </span><span class="o">*</span><span class="n">env</span><span class="p">,</span><span class="w"> </span><span class="n">jobject</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Hello from C!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>Then, in Java, the function is called like so:
</p>
<div class="mw-highlight mw-highlight-lang-java mw-content-ltr" dir="ltr"><pre><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">HelloJNI</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// "hello" refers to libhello.so on Linux</span>
<span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="na">loadLibrary</span><span class="p">(</span><span class="s">"hello"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kd">native</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">sayHello</span><span class="p">();</span>
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HelloJNI</span><span class="p">().</span><span class="na">sayHello</span><span class="p">();</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
<div class="mw-heading mw-heading2"><h2 id="Mapping_types">Mapping types</h2></div>
<p>The following table shows the mapping of types between Java (JNI) and native code.
</p>
<table class="wikitable">
<tbody><tr>
<th>C Type
</th>
<th>Java Language Type
</th>
<th>Description
</th>
<th>Type signature
</th></tr>
<tr>
<td><span class="monospaced">unsigned char<br>uint8_t</span>
</td>
<td><span class="monospaced">jboolean</span>
</td>
<td>unsigned 8 bits
</td>
<td><span class="monospaced">Z</span>
</td></tr>
<tr>
<td><span class="monospaced">signed char<br>int8_t</span>
</td>
<td><span class="monospaced">jbyte</span>
</td>
<td>signed 8 bits
</td>
<td><span class="monospaced">B</span>
</td></tr>
<tr>
<td><span class="monospaced">unsigned short<br>uint16_t</span>
</td>
<td><span class="monospaced">jchar</span>
</td>
<td>unsigned 16 bits
</td>
<td><span class="monospaced">C</span>
</td></tr>
<tr>
<td><span class="monospaced">short<br>int16_t</span>
</td>
<td><span class="monospaced">jshort</span>
</td>
<td>signed 16 bits
</td>
<td><span class="monospaced">S</span>
</td></tr>
<tr>
<td><span class="monospaced">int<br>int32_t</span>
</td>
<td><span class="monospaced">jint</span>
</td>
<td>signed 32 bits
</td>
<td><span class="monospaced">I</span>
</td></tr>
<tr>
<td><span class="monospaced">long long<br>int64_t</span>
</td>
<td><span class="monospaced">jlong</span>
</td>
<td>signed 64 bits
</td>
<td><span class="monospaced">J</span>
</td></tr>
<tr>
<td><span class="monospaced">float</span>
</td>
<td><span class="monospaced">jfloat</span>
</td>
<td>32 bits
</td>
<td><span class="monospaced">F</span>
</td></tr>
<tr>
<td><span class="monospaced">double</span>
</td>
<td><span class="monospaced">jdouble</span>
</td>
<td>64 bits
</td>
<td><span class="monospaced">D</span>
</td></tr>
<tr>
<td><span class="monospaced">void</span>
</td>
<td>
</td>
<td>
</td>
<td><span class="monospaced">V</span>
</td></tr></tbody></table>
<p>In addition, the signature <code>"L fully-qualified-class ;"</code> would mean the class uniquely specified by that name; e.g., the signature <code>"Ljava/lang/String;"</code> refers to the class <code><a rel="nofollow" class="external text" href="https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/lang/String.html">java.lang.String</a></code>. Also, prefixing <code>[</code> to the signature makes the array of that type; for example, <code>[I</code> means the int array type (<code>int[]</code>). Finally, a <code>void</code> signature uses the <code>V</code> code.
</p><p>These types are interchangeable. One can use <code>jint</code> where you normally use an <code>int</code>, and vice versa, without any <a href="Type_conversion" title="Type conversion">typecasting</a> required. However, mapping between Java Strings and arrays to native strings and arrays is different. If a <code>jstring</code> is used where a <code>char *</code> would be, the code could crash the JVM.
</p>
<div class="mw-heading mw-heading2"><h2 id="Performance">Performance</h2></div>
<p>JNI incurs considerable overhead and performance loss under certain circumstances:<sup id="cite_ref-StackOverflow:_What_makes_JNI_calls_slow?_6-0" class="reference"><a href="#cite_note-StackOverflow:_What_makes_JNI_calls_slow?-6"><span class="cite-bracket">[</span>6<span class="cite-bracket">]</span></a></sup>
</p>
<ul><li>Function calls to JNI methods are expensive, especially when calling a method repeatedly.</li>
<li>Native methods are not inlined by the JVM, nor can the method be <a href="Just-in-time_compilation" title="Just-in-time compilation">JIT compiled</a>, as the method is already compiled.</li>
<li>A Java array may be copied for access in native code, and later copied back. The cost can be linear in the size of the array.</li>
<li>If the method is passed an object, or needs to make a callback, then the native method will likely be making its own calls to the JVM. Accessing Java fields, methods and types from the native code requires something similar to <a href="Reflective_programming" title="Reflective programming">reflective programming</a> (reflection). Signatures are specified in strings and queried from the JVM. This is both slow and error-prone.</li>
<li>Java Strings are objects, have length and are encoded. Accessing or creating a string may require an O(n) copy.</li></ul>
<div class="mw-heading mw-heading2"><h2 id="Foreign_Function_and_Memory_API">Foreign Function and Memory API</h2></div>
<p>Java 22 introduced the Foreign Function and Memory API, located in <code><a rel="nofollow" class="external text" href="https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/lang/foreign/package-summary.html">java.lang.foreign</a></code> which can be seen as a sort of successor to the Java Native Interface.<sup id="cite_ref-javaFFI_7-0" class="reference"><a href="#cite_note-javaFFI-7"><span class="cite-bracket">[</span>7<span class="cite-bracket">]</span></a></sup> It has a simpler interface and generally requires less boilerplate than JNI, due to no longer requiring the inclusion of <code><jni.h></code> in the foreign library to invoke. There is no use of the keyword <code>native</code> in Foreign Function and Memory API. It supports <a href="Region-based_memory_management" title="Region-based memory management">region-based memory management</a>. The class <code>MemorySegment</code> models a contiguous segment of memory which can lie inside or outside the JVM heap, and a <code>MemorySegment</code> is allocated using a <code>Arena</code> which controls the lifetime of the region of memory backing its allocated segment of memory.
</p>
<div class="mw-highlight mw-highlight-lang-java mw-content-ltr" dir="ltr"><pre><span class="kn">import</span><span class="w"> </span><span class="nn">java.lang.foreign.*</span><span class="p">;</span>
<span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ForeignMemoryExample</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">(</span><span class="n">Arena</span><span class="w"> </span><span class="n">arena</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arena</span><span class="p">.</span><span class="na">ofConfined</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">MemorySegment</span><span class="w"> </span><span class="n">segment</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arena</span><span class="p">.</span><span class="na">allocate</span><span class="p">(</span><span class="mi">5</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">Double</span><span class="p">.</span><span class="na">BYTES</span><span class="p">);</span>
<span class="w"> </span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">segment</span><span class="p">.</span><span class="na">setAtIndex</span><span class="p">(</span><span class="n">ValueLayout</span><span class="p">.</span><span class="na">JAVA_DOUBLE</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">1.1</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">segment</span><span class="p">.</span><span class="na">getAtIndex</span><span class="p">(</span><span class="n">ValueLayout</span><span class="p">.</span><span class="na">JAVA_DOUBLE</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">printf</span><span class="p">(</span><span class="s">"Value at index %d: %d%n"</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">value</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>In a sense, Java Foreign Function and Memory API allows for direct memory allocation outside the JVM heap (i.e. the operating system heap), through <code>Arena.allocate()</code> and <code>MemorySegment.allocateNative()</code> which allocate raw memory directly, while <code>Arena.close()</code> and <code>MemorySegment.close()</code> are used to deallocate/release the memory segment.
</p><p>As a <a href="Foreign_function_interface" title="Foreign function interface">foreign function interface</a>, <code>java.lang.foreign</code> introduces <code>Linker</code> for accessing between foreign functions from Java (to and from), <code>SymbolLookup</code> to retrieve the address of a symbol in a library, and <code>FunctionDescriptor</code> for modelling a foreign function signature.
</p>
<div class="mw-highlight mw-highlight-lang-java mw-content-ltr" dir="ltr"><pre><span class="kn">import</span><span class="w"> </span><span class="nn">java.lang.foreign.*</span><span class="p">;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">java.lang.invoke.MethodHandle</span><span class="p">;</span>
<span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">ForeignFunctionExample</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Throwable</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Linker</span><span class="w"> </span><span class="n">linker</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Linker</span><span class="p">.</span><span class="na">nativeLinker</span><span class="p">();</span>
<span class="w"> </span>
<span class="w"> </span><span class="n">SymbolLookup</span><span class="w"> </span><span class="n">stdlib</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">linker</span><span class="p">.</span><span class="na">defaultLookup</span><span class="p">();</span>
<span class="w"> </span>
<span class="w"> </span><span class="n">MethodHandle</span><span class="w"> </span><span class="n">printf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">linker</span><span class="p">.</span><span class="na">downcallHandle</span><span class="p">(</span>
<span class="w"> </span><span class="n">stdlib</span><span class="p">.</span><span class="na">findOrThrow</span><span class="p">(</span><span class="s">"printf"</span><span class="p">),</span>
<span class="w"> </span><span class="n">FunctionDescriptor</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ValueLayout</span><span class="p">.</span><span class="na">JAVA_INT</span><span class="p">,</span><span class="w"> </span><span class="n">ValueLayout</span><span class="p">.</span><span class="na">ADDRESS</span><span class="p">)</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="n">MethodHandle</span><span class="w"> </span><span class="n">strlen</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">linker</span><span class="p">.</span><span class="na">downcallHandle</span><span class="p">(</span>
<span class="w"> </span><span class="n">stdlib</span><span class="p">.</span><span class="na">findOrThrow</span><span class="p">(</span><span class="s">"strlen"</span><span class="p">),</span>
<span class="w"> </span><span class="n">FunctionDescriptor</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ValueLayout</span><span class="p">.</span><span class="na">JAVA_LONG</span><span class="p">,</span><span class="w"> </span><span class="n">ValueLayout</span><span class="p">.</span><span class="na">ADDRESS</span><span class="p">)</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">(</span><span class="n">Arena</span><span class="w"> </span><span class="n">arena</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Arena</span><span class="p">.</span><span class="na">ofConfined</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">MemorySegment</span><span class="w"> </span><span class="n">formatString</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arena</span><span class="p">.</span><span class="na">allocateUtf8String</span><span class="p">(</span><span class="s">"Hello, %s!\n"</span><span class="p">);</span>
<span class="w"> </span><span class="n">MemorySegment</span><span class="w"> </span><span class="n">argString</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arena</span><span class="p">.</span><span class="na">allocateUtf8String</span><span class="p">(</span><span class="s">"World"</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">.</span><span class="na">invokeExact</span><span class="p">(</span><span class="n">formatString</span><span class="p">,</span><span class="w"> </span><span class="n">argString</span><span class="p">);</span><span class="w"> </span><span class="c1">// prints "Hello, World!"</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">strlen</span><span class="p">.</span><span class="na">invokeExact</span><span class="p">(</span><span class="n">formatString</span><span class="p">);</span><span class="w"> </span><span class="c1">// len = 5</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
<div class="mw-heading mw-heading2"><h2 id="Alternatives">Alternatives</h2></div>
<p>Microsoft's proprietary implementation of a Java Virtual Machine (<a href="Visual_J%2B%2B" title="Visual J++">Visual J++</a>) had a similar mechanism for calling native code from Java, called the <i>Raw Native Interface</i> (<i>RNI</i>). In addition, it had an easy way to call existing native code that was not itself aware of Java, such as (but not limited to) the Windows API, called <i>J/Direct</i>. However, following the <a href="Visual_J%2B%2B#Litigation_against_J++" title="Visual J++">Sun–Microsoft litigation</a> about this implementation, <a href="Visual_J%2B%2B" title="Visual J++">Visual J++</a> is no longer maintained.
</p><p>RNI was less clumsy to use than JNI, because no bookkeeping with a Java environment pointer was needed. Instead, all Java objects could be accessed directly. To facilitate this, a tool was used to generate header files from Java classes. Similarly, J/Direct was easier to use than using the necessary intermediate native library and JNI.
</p><p><a href="Java_Native_Access" title="Java Native Access">Java Native Access (JNA)</a> is a community-developed library that provides Java programmers easy access to native shared libraries without using JNI. However, this requires the redistribution of the dependent jar library. The tradeoff is between JNI being harder to code and JNA being slower.<sup id="cite_ref-8" class="reference"><a href="#cite_note-8"><span class="cite-bracket">[</span>8<span class="cite-bracket">]</span></a></sup> JNI is built in to core Java.
</p><p>Since Java 22, the newer Foreign Function and Memory API is encouraged for use over JNI, due to the reduced boilerplate and simplified interface.<sup id="cite_ref-javaFFI_7-1" class="reference"><a href="#cite_note-javaFFI-7"><span class="cite-bracket">[</span>7<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-heading mw-heading2"><h2 id="See_also">See also</h2></div>
<ul><li><a href="GIWS_(software)" title="GIWS (software)">GIWS (software)</a></li>
<li><a href="GlueGen" title="GlueGen">GlueGen</a></li>
<li><a href="Platform_Invocation_Services" title="Platform Invocation Services">Platform Invocation Services</a></li>
<li><a href="SWIG" title="SWIG">SWIG</a></li>
<li><a href="C%2B%2B/CLI" title="C++/CLI">C++/CLI</a></li>
<li><a href="Libffi" title="Libffi">libffi</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="References">References</h2></div>
<style data-mw-deduplicate="TemplateStyles:r1239543626">
/* start https://en.wikipedia.org/ */
.mw-parser-output .reflist{margin-bottom:0.5em;list-style-type:decimal}@media screen{.mw-parser-output .reflist{font-size:90%}}.mw-parser-output .reflist .references{font-size:100%;margin-bottom:0;list-style-type:inherit}.mw-parser-output .reflist-columns-2{column-width:30em}.mw-parser-output .reflist-columns-3{column-width:25em}.mw-parser-output .reflist-columns{margin-top:0.3em}.mw-parser-output .reflist-columns ol{margin-top:0}.mw-parser-output .reflist-columns li{page-break-inside:avoid;break-inside:avoid-column}.mw-parser-output .reflist-upper-alpha{list-style-type:upper-alpha}.mw-parser-output .reflist-upper-roman{list-style-type:upper-roman}.mw-parser-output .reflist-lower-alpha{list-style-type:lower-alpha}.mw-parser-output .reflist-lower-greek{list-style-type:lower-greek}.mw-parser-output .reflist-lower-roman{list-style-type:lower-roman}
/* end https://en.wikipedia.org/ */
</style><div class="reflist reflist-columns references-column-width" style="column-width: 30em;">
<ol class="references">
<li id="cite_note-role-1"><span class="mw-cite-backlink"><b><a href="#cite_ref-role_1-0">^</a></b></span> <span class="reference-text"><style data-mw-deduplicate="TemplateStyles:r1238218222">
/* start https://en.wikipedia.org/ */
.mw-parser-output cite.citation{font-style:inherit;word-wrap:break-word}.mw-parser-output .citation q{quotes:"\"""\"""'""'"}.mw-parser-output .citation:target{background-color:rgba(0,127,255,0.133)}.mw-parser-output .id-lock-free.id-lock-free a{background:url("./mw/Lock-green.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-limited.id-lock-limited a,.mw-parser-output .id-lock-registration.id-lock-registration a{background:url("./mw/Lock-gray-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .id-lock-subscription.id-lock-subscription a{background:url("./mw/Lock-red-alt-2.svg")right 0.1em center/9px no-repeat}.mw-parser-output .cs1-ws-icon a{background:url("./mw/Wikisource-logo.svg")right 0.1em center/12px no-repeat}body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-free a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-limited a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-registration a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .id-lock-subscription a,body:not(.skin-timeless):not(.skin-minerva) .mw-parser-output .cs1-ws-icon a{background-size:contain;padding:0 1em 0 0}.mw-parser-output .cs1-code{color:inherit;background:inherit;border:none;padding:inherit}.mw-parser-output .cs1-hidden-error{display:none;color:var(--color-error,#d33)}.mw-parser-output .cs1-visible-error{color:var(--color-error,#d33)}.mw-parser-output .cs1-maint{display:none;color:#085;margin-left:0.3em}.mw-parser-output .cs1-kern-left{padding-left:0.2em}.mw-parser-output .cs1-kern-right{padding-right:0.2em}.mw-parser-output .citation .mw-selflink{font-weight:inherit}@media screen{.mw-parser-output .cs1-format{font-size:95%}html.skin-theme-clientpref-night .mw-parser-output .cs1-maint{color:#18911f}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output .cs1-maint{color:#18911f}}
/* end https://en.wikipedia.org/ */
</style><cite class="citation web cs1"><a rel="nofollow" class="external text" href="https://docs.oracle.com/en/java/javase/11/docs/specs/jni/intro.html#java-native-interface-overview">"Java Native Interface Overview"</a>. <i>The Java Native Interface Programmer's Guide and Specification</i><span class="reference-accessdate">. Retrieved <span class="nowrap">2018-12-27</span></span>.</cite></span>
</li>
<li id="cite_note-2"><span class="mw-cite-backlink"><b><a href="#cite_ref-2">^</a></b></span> <span class="reference-text"><cite class="citation web cs1"><a rel="nofollow" class="external text" href="https://web.archive.org/web/20080330002620/http://today.java.net/pub/a/today/2006/10/19/invoking-assembly-language-from-java.html">"Invoking Assembly Language Programs from Java"</a>. Java.net. 2006-10-19. Archived from <a rel="nofollow" class="external text" href="http://today.java.net/pub/a/today/2006/10/19/invoking-assembly-language-from-java.html">the original</a> on 2008-03-30<span class="reference-accessdate">. Retrieved <span class="nowrap">2007-10-06</span></span>.</cite></span>
</li>
<li id="cite_note-3"><span class="mw-cite-backlink"><b><a href="#cite_ref-3">^</a></b></span> <span class="reference-text"><cite class="citation web cs1"><a rel="nofollow" class="external text" href="https://web.archive.org/web/20071011014140/http://today.java.net/pub/a/today/2007/10/04/launch-java-applications-from-assembly-language-programs.html">"Launch Java Applications from Assembly Language Programs"</a>. Java.net. 2006-10-19. Archived from <a rel="nofollow" class="external text" href="http://today.java.net/pub/a/today/2007/10/04/launch-java-applications-from-assembly-language-programs.html">the original</a> on 2007-10-11<span class="reference-accessdate">. Retrieved <span class="nowrap">2007-10-04</span></span>.</cite></span>
</li>
<li id="cite_note-4"><span class="mw-cite-backlink"><b><a href="#cite_ref-4">^</a></b></span> <span class="reference-text">The Invocation API. Sun Microsystems. <a rel="nofollow" class="external free" href="https://docs.oracle.com/en/java/javase/11/docs/specs/jni/invocation.html">https://docs.oracle.com/en/java/javase/11/docs/specs/jni/invocation.html</a></span>
</li>
<li id="cite_note-jniModifiedUtf-5"><span class="mw-cite-backlink"><b><a href="#cite_ref-jniModifiedUtf_5-0">^</a></b></span> <span class="reference-text"><cite class="citation web cs1"><a rel="nofollow" class="external text" href="http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html#wp16542">"JNI Types and Data Structures"</a>.</cite></span>
</li>
<li id="cite_note-StackOverflow:_What_makes_JNI_calls_slow?-6"><span class="mw-cite-backlink"><b><a href="#cite_ref-StackOverflow:_What_makes_JNI_calls_slow?_6-0">^</a></b></span> <span class="reference-text"><cite class="citation web cs1"><a rel="nofollow" class="external text" href="https://stackoverflow.com/a/7809300/1068537">"Java: What makes JNI calls slow?"</a>. <i>Stack Overflow</i>.</cite></span>
</li>
<li id="cite_note-javaFFI-7"><span class="mw-cite-backlink">^ <a href="#cite_ref-javaFFI_7-0"><sup><i><b>a</b></i></sup></a> <a href="#cite_ref-javaFFI_7-1"><sup><i><b>b</b></i></sup></a></span> <span class="reference-text"><cite class="citation web cs1"><a rel="nofollow" class="external text" href="https://openjdk.org/jeps/454">"JEP 454: Foreign Function & Memory API"</a>. OpenJDK. 7 April 2025.</cite></span>
</li>
<li id="cite_note-8"><span class="mw-cite-backlink"><b><a href="#cite_ref-8">^</a></b></span> <span class="reference-text"><cite id="CITEREFZakusylo" class="citation web cs1">Zakusylo, Alexander. <a rel="nofollow" class="external text" href="https://github.com/zakgof/java-native-benchmark">"Github is also the original JNA source. JNA vs JNI benchmark speed tests"</a>. <i>Github</i>. Github<span class="reference-accessdate">. Retrieved <span class="nowrap">30 March</span> 2023</span>.</cite></span>
</li>
</ol></div>
<div class="mw-heading mw-heading2"><h2 id="Bibliography">Bibliography</h2></div>
<style data-mw-deduplicate="TemplateStyles:r1239549316">
/* start https://en.wikipedia.org/ */
.mw-parser-output .refbegin{margin-bottom:0.5em}.mw-parser-output .refbegin-hanging-indents>ul{margin-left:0}.mw-parser-output .refbegin-hanging-indents>ul>li{margin-left:0;padding-left:3.2em;text-indent:-3.2em}.mw-parser-output .refbegin-hanging-indents ul,.mw-parser-output .refbegin-hanging-indents ul li{list-style:none}@media(max-width:720px){.mw-parser-output .refbegin-hanging-indents>ul>li{padding-left:1.6em;text-indent:-1.6em}}.mw-parser-output .refbegin-columns{margin-top:0.3em}.mw-parser-output .refbegin-columns ul{margin-top:0}.mw-parser-output .refbegin-columns li{page-break-inside:avoid;break-inside:avoid-column}@media screen{.mw-parser-output .refbegin{font-size:90%}}
/* end https://en.wikipedia.org/ */
</style><div class="refbegin" style="">
<ul><li><cite id="CITEREFGordon1998" class="citation book cs1">Gordon, Rob (March 1998). <a rel="nofollow" class="external text" href="http://www.informit.com/store/product.aspx?isbn=9780136798958"><i>Essential Jni: Java Native Interface</i></a> (1st ed.). <a href="Prentice_Hall" title="Prentice Hall">Prentice Hall</a>. p. 498. <a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a> <bdi>0-13-679895-0</bdi>.</cite></li>
<li><cite id="CITEREFLiang1999" class="citation book cs1">Liang, Sheng (June 20, 1999). <a rel="nofollow" class="external text" href="http://www.informit.com/store/product.aspx?isbn=9780201325775"><i>Java(TM) Native Interface: Programmer's Guide and Specification</i></a> (1st ed.). <a href="Prentice_Hall" title="Prentice Hall">Prentice Hall</a>. p. 320. <a href="ISBN_(identifier)" class="mw-redirect" title="ISBN (identifier)">ISBN</a> <bdi>0-201-32577-2</bdi>.</cite></li></ul>
</div>
<div class="mw-heading mw-heading2"><h2 id="External_links">External links</h2></div>
<ul><li><a rel="nofollow" class="external text" href="https://docs.oracle.com/javase/8/docs/technotes/guides/jni/">Oracle's JNI 6.0 API Specification</a></li>
<li><a rel="nofollow" class="external text" href="https://web.archive.org/web/20120728074805/http://java.sun.com/docs/books/jni/">Java Native Interface: Programmer's Guide and Specification</a></li>
<li><a rel="nofollow" class="external text" href="https://web.archive.org/web/20111014002625/http://developer.apple.com/java/jniuniversal.html">JNI in XCode from Apple</a></li>
<li><a rel="nofollow" class="external text" href="http://www.codeproject.com/KB/debug/jni_ex.aspx">Exception handling in JNI</a></li>
<li><a rel="nofollow" class="external text" href="https://www.scapix.com/java_link">Java Link</a> (modern C++17 wrapper for JNI)</li></ul></div><!--htdig_noindex--><div><div class="zim-footer">
This article is issued from <a class="external text" title="Last edited on 2025-07-09" href="https://en.wikipedia.org/wiki/?title=Java_Native_Interface&oldid=1299565077">Wikipedia</a>. The text is available under <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-Share Alike 4.0</a> unless otherwise noted. Additional terms may apply for the media files.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
</body></html>